package com.example.designpattern.creator.singleton;

import java.io.Serializable;

/**
 * Example for singleton pattern
 * @author synv
 *
 */
public class SingletonExamples {
	public static void main(String[] args) {
		//BestChoiceSingleton.getInstance();
		
		System.out.println(EagerSingleton.TEST);
	}
}

/**
 * Best Choice Singleton
 */
class BestChoiceSingleton implements Serializable{

	private static final long serialVersionUID = 1L;
	
	public BestChoiceSingleton() {
		System.out.println("Create Instance");
	}
	
	private static class Holder {
		public static final BestChoiceSingleton INSTANCE = new BestChoiceSingleton();
	}
	
	public static BestChoiceSingleton getInstance() {
		return Holder.INSTANCE;
	}
	
	protected Object readObject() {
		return getInstance();
	}
}

/**
 * Eager Singleton
 * Instance is created irrespective of it is required in runtime or not.
 * If instance of this class is not big, and you can live with it being unused, this is best approach.
 */
class EagerSingleton {
	private static volatile EagerSingleton instance = new EagerSingleton();
	public static final String TEST = "TEST";
	public EagerSingleton() {
		System.out.println("Create new eager singleton instance");
	}
	public static EagerSingleton getInstance() {
		return instance;
	}
}

/**
 * Lazy Singleton
 * 
 */
class LazySingleton {
	private static volatile LazySingleton instance = null;
	public LazySingleton() {
		
	}
	public static LazySingleton getInstance() {
		if(instance == null) {
			synchronized (LazySingleton.class) {
				/*
				 * DOUBLE CHECK to ensure that only one instance is created in application.
				 * Suppose there are two threads T1 & T2. Both comes to create LazySingleton instance and execute "instance == null".
				 * Now both identified instance to null thus assume they need to create new instance. 
				 * If we do not double check, they sequentially go to synchronized block and create new instance. So there are two instance in application.
				 */
				if(instance == null) {
					instance = new LazySingleton();
				}
			}
		}
		return instance;
	}
}
